﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Medianamik.Core.DAL;
using Medianamik.Core;
using System.Web.Security;
using Medianamik.Core.Interfaces;
using Medianamik.Core.Profile;
using System.Web.Profile;
using Medianamik.Core.Logging;

namespace Medianamik.Core.Security
{
    /// <summary>
    /// Représentation d'un usager Médianamik. Extension de MembershipUser
    /// </summary>

    [Serializable]
    public class MedianamikUser : System.Web.Security.MembershipUser, ILoggable
    {
        public MedianamikUser(string providerName,
                              string userName,
            object providerUserKey,
            string email,
            string passwordQuestion,
            string comment,
            bool isApproved,
            bool isLockedOut,
            DateTime creationDate,
            DateTime lastLoginDate,
            DateTime lastActivityDate,
            DateTime lastPasswordChangedDate,
            DateTime lasLockedOutDate) :
            base(providerName,
                     userName,
                     providerUserKey,
                     email,
                     passwordQuestion,
                     comment,
                     isApproved,
                     isLockedOut,
                     creationDate,
                     lastLoginDate,
                     lastActivityDate,
                     lastPasswordChangedDate,
                     lasLockedOutDate)
        { }

        public MedianamikUser(MembershipUser pMemUser)
            : this(pMemUser.ProviderName,
                pMemUser.UserName,
                pMemUser.ProviderUserKey,
                pMemUser.Email,
                pMemUser.PasswordQuestion,
                pMemUser.Comment,
                pMemUser.IsApproved,
                pMemUser.IsLockedOut,
                pMemUser.CreationDate,
                pMemUser.LastLoginDate,
                pMemUser.LastActivityDate,
                pMemUser.LastPasswordChangedDate,
                pMemUser.LastLockoutDate)

        { }

        public UserProfile GetProfile()
        {
            return (UserProfile)ProfileBase.Create(UserName);
        }

        public IEnumerable<Group> Groups
        {
            get
            {
                return Roles.GetGroupsForUser(UserName).SelectMany(groupName =>
                    SecurityManager.AllGroups.Where(g => g.Name.Equals(groupName)));
            }
        }

        public bool CanAccessProperty(NodeTypeProperty pNodeTypeProperty)
        {
            return !pNodeTypeProperty.Roles.Any()
                || pNodeTypeProperty.Roles.Any(role => Roles.IsUserInRole(role));
        }

        public bool CanDeleteAllInstancesOfANode
        {
            get
            {
                return Roles.IsUserInRole("DeleteAllInstancesOfANode");
            }
        }

        public bool CanDeleteNodeBranch
        {
            get
            {
                return Roles.IsUserInRole("DeleteNodeBranch");
            }
        }

        public bool CanEditGroup(Group group)
        {
            var mayManageOwnGroup = GetProfile().MayManageOwnGroup;

            return Groups.Any(g => g.IsParent(group) || (mayManageOwnGroup && g.Equals(group)));
        }

        public bool CanEditChildGroups(Group group)
        {
            return Groups.Any(g => g.Equals(group) || g.IsParent(group));
        }

        private bool? _isSuperAdmin;
        public bool IsSuperAdmin
        {
            get
            {
                if (_isSuperAdmin == null)
                    _isSuperAdmin = Groups.Any(g => g.ID.Equals(MedianamikGroups.SuperAdmins));

                return _isSuperAdmin.GetValueOrDefault();
            }
        }

        #region Logging

        Guid? ILoggable.LogObjectID
        {
            get
            {
                return (Guid?)ProviderUserKey;
            }
        }
        string ILoggable.LogObjectName
        {
            get
            {
                return UserName;
            }
        }
        LogEntryType ILoggable.LogType
        {
            get
            {
                return LogEntryType.User;
            }
        }

        #endregion
    }
}
